package net.gz01.wallet.web.controller.customer;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.*;

import javax.imageio.ImageIO;

import net.gz01.util.ZOMoney;
import net.gz01.wallet.common.*;
import net.gz01.wallet.message.BaseReq;
import net.gz01.wallet.web.model.*;
import net.gz01.wallet.web.model.Dictionary;
import org.jxls.common.Context;

import com.jfinal.aop.Clear;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;

import net.gz01.util.ZODate;
import net.gz01.util.ZOExcel;
import net.gz01.wallet.message.AccountBalanceChangeResp;
import net.gz01.wallet.web.config.SystemConfig;
import net.gz01.wallet.web.config.SystemEnum;
import net.gz01.wallet.web.config.SystemEnum.BizType;
import net.gz01.wallet.web.config.SystemEnum.OrderStatus;
import net.gz01.wallet.web.config.SystemEnum.Resp;
import net.gz01.wallet.web.controller.BaseController;
import net.gz01.wallet.web.service.AccountService;
import net.gz01.wallet.web.service.CalcFeeService;

public class OrderController extends BaseController {
	private CalcFeeService feeService = new CalcFeeService();
	private AccountService accountService = new AccountService();

	public void index() {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		if (merchUser == null) {
			render("");
			return;
		}
		setAttr("status", "all");
		setAttr("bizTypeList", Dictionary.dao.selectBizType());
		render("order.html");
	}

	public void detail() {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		TradeOrder order = TradeOrder.dao.select(merchUser.getMerchCode(), getPara("id"));
		if(order == null){
			redirect("/customer/login");
			return;
		}
		if (BizType.Charge.getValue().equals(order.getBizType())) {
			setAttr("youliAccount", YouliAccount.dao.findById(order.getYouliAccountId()));
		}
		StringBuilder shareUrl = new StringBuilder(SystemConfig.config.get("local_domain"));
		shareUrl.append("/customer/order/share?id=");
		shareUrl.append(order.getId());
		setAttr("order", order);
		Long allAmt = Math.abs(order.getAmount()) + Math.abs(order.getFee());
		if(BizType.Charge.getValue().equals(order.getBizType())){
			allAmt = Math.abs(order.getAmount()) - Math.abs(order.getFee());
		}
		setAttr("allAmt", ZOMoney.changeF2Y(allAmt));
		setAttr("shareUrl", shareUrl.toString());
		render("orderDetail.html");
	}

	@Clear
	public void share() {
		TradeOrder order = TradeOrder.dao.findById(getPara("id"));
		if (BizType.Charge.getValue().equals(order.getBizType())) {
			setAttr("youliAccount", YouliAccount.dao.findById(order.getYouliAccountId()));
		}
		setAttr("order", order);
		render("shareShow.html");
	}

	public void listJson() {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		if (merchUser == null) {
//			render("login.html");
			Page<TradeOrder> pageResult = new Page<> ();
			renderJson(new PageRespon(pageResult));
			return;
		}
		ZOSearchCondition sc = super.getSearchCondition();
		sc.put("merchCode", merchUser.getMerchCode());
		if(OrderStatus.InProcess.getValue().equals(sc.getStr("orderStatus"))){
			sc.put("orderStatus", OrderStatus.FirstReview.getValue());
			sc.put("orderStatus2", OrderStatus.SecondReview.getValue());
			sc.put("orderStatus3", OrderStatus.ThirdReview.getValue());
			sc.put("orderStatus4", OrderStatus.WaitTransferOut.getValue());
		}
		Page<TradeOrder> pageResult = TradeOrder.dao.searchOrder(sc);
		renderJson(new PageRespon(pageResult));
	}

	/**
	 * 收款(充值)制单
	 */
	public void charge() {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		String youliAccountId = getPara("youliAccountId");
		YouliAccount youliAccount = YouliAccount.dao.findById(youliAccountId);
		if (youliAccount == null) {
			renderFail("友利收款账户不存在");
			return;
		}

		String chargeAmount = getPara("amount");
		if (StrKit.isBlank(chargeAmount)) {
			renderFail("金额必填");
			return;
		}

		BigDecimal amount = new BigDecimal(chargeAmount).multiply(new BigDecimal("100"));
		if (amount == null || amount.longValue() <= 0L) {
			renderFail("金额错误，金额必须大于0");
			return;
		}
		String merchCode = merchUser.getMerchCode();
		Merch merch = Merch.dao.selectByMerchCode(merchCode);
		if (merch == null) {
			renderFail("用户信息错误，请联系管理员");
			return;
		}
		// 检查充值的交易配置
		TradeConfig tradeConfig = TradeConfig.dao.selectCharge(merchCode);
		if (tradeConfig == null) {
			renderFail("找不到充值交易配置，请联系管理员");
			return;
		}
		Integer fee = feeService.getFee(amount.intValue(), tradeConfig.getFeeId());
		if (fee < 0) {
			renderFail("费率模式不存在");
			return;
		}
		if (amount.longValue() < fee.longValue()) {
			renderFail("充值(收款)金额不足以支付手续费");
			return;
		}

		//风控规则判断
		BaseReq req = new BaseReq();
		req.setBizType(BizType.Charge.getValue());
		req.setMerchCode(merchCode);

		RiskRule riskRule = RiskRule.dao.findById(tradeConfig.getRiskRuleId());
		RiskRuleCheck ruleCheck = new RiskRuleCheck(amount.longValue(), BizType.Charge.getValue() , req, riskRule);
		String riskRuleMsg = ruleCheck.check();
		if (StrKit.notBlank(riskRuleMsg)) {
			renderFail(SystemEnum.Resp.Fail.getCode()+":" + riskRuleMsg);
			return;
		}


		// 保存收款(充值)订单
		TradeOrder chargeOrder = new TradeOrder();
		chargeOrder.setId(ZOIDGenerate.getUUID());
		chargeOrder.setMerchName(merch.getName());
		chargeOrder.setMerchCode(merchCode);
		chargeOrder.setRealName(merch.getLegalPerson());
		chargeOrder.setUserName(merchUser.getUserName());
		chargeOrder.setBizType(BizType.Charge.getValue());
		chargeOrder.setChannelCode(tradeConfig.getChannelCode());
		chargeOrder.setAccountNo(youliAccount.getAccountNo());
		chargeOrder.setAccountName(youliAccount.getAccountName());
		chargeOrder.setBankName(youliAccount.getBankName());
		chargeOrder.setOpeningBankName(youliAccount.getOpeningBankName());
		chargeOrder.setOpeningBankNo(youliAccount.getOpeningBankNo());
		chargeOrder.setProvince(youliAccount.getProvince());
		chargeOrder.setCity(youliAccount.getCity());
		chargeOrder.setYouliAccountId(youliAccount.getId());
		chargeOrder.setOrderNo(ZOIDGenerate.getSixOrderNo());
		chargeOrder.setOutOrderNo(chargeOrder.getOrderNo());
		chargeOrder.setAmount(amount.longValue());
		chargeOrder.setFee(fee.longValue());
		chargeOrder.setPayer(getPara("payer"));
		chargeOrder.setPhoneNo(getPara("phoneNo"));
		if (StrKit.isBlank(getPara("goodsName"))) {
			chargeOrder.setGoodsName("收款");
		} else {
			chargeOrder.setGoodsName(getPara("goodsName"));
		}
		chargeOrder.setOrderStatus(OrderStatus.FirstReview.getValue());
		chargeOrder.setRespCode(Resp.Success.getCode());
		chargeOrder.setRespMsg("已提交");
		chargeOrder.setCreateTime(ZODate.getDateTime());
		chargeOrder.setCreateUser(merchUser.getUserName());
		chargeOrder.save();
		renderSuccess(chargeOrder.getId());
	}

	/**
	 * 付款
	 */
	public void payment() {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		Merch merch = Merch.dao.selectByMerchCode(merchUser.getMerchCode());
		if (merch == null) {
			renderFail("用户信息错误，请联系管理员");
			return;
		}
		String remark = getPara("remark");

		String paymentAmount = getPara("amount");
		String tradeType = getPara("tradeType");
		if (StrKit.isBlank(paymentAmount)) {
			renderFail("金额必填");
			return;
		}
		BigDecimal amount = new BigDecimal(paymentAmount).multiply(new BigDecimal("100"));
		if (amount == null || amount.longValue() <= 0) {
			renderFail("金额错误，金额必须大于0");
			return;
		}
		Contacts contacts = Contacts.dao.findById(getPara("contactsId"));
		if (contacts == null) {
			renderFail("找不到收款人");
			return;
		}

		String bizType = "";
		if ("bankCard".equals(contacts.getAccountType())) {
			if ("withdraw".equals(tradeType)) {
				bizType = contacts.getIsCompany() ? BizType.Withdraw_Company.getValue() : BizType.Withdraw_Personal.getValue();
			}
			if ("transfer".equals(tradeType)) {
				bizType = contacts.getIsCompany() ? BizType.DF_Company.getValue() : BizType.DF_Personal.getValue();
			}
		}

		if ("wallet".equals(contacts.getAccountType())) {
			bizType = BizType.TransferOut.getValue();
			if (merch.getCode().equals(contacts.getAccountNo())) {
				renderFail("不能给自己转账");
				return;
			}
		}

		if (StrKit.isBlank(bizType)) {
			renderFail("交易类型错误，找不到对应的交易类型");
			return;
		}

		// 检查充值的交易配置
		TradeConfig tradeConfig = TradeConfig.dao.select(merch.getCode(), bizType);
		if (tradeConfig == null) {
			renderFail("找不到交易配置，请联系管理员");
			return;
		}
		Integer fee = feeService.getFee(amount.intValue(), tradeConfig.getFeeId());
		if (fee < 0) {
			renderFail("费率模式不存在");
			return;
		}


		//风控规则判断
		BaseReq req = new BaseReq();
		req.setBizType(bizType);
		req.setMerchCode(merch.getCode());

		RiskRule riskRule = RiskRule.dao.findById(tradeConfig.getRiskRuleId());
		RiskRuleCheck ruleCheck = new RiskRuleCheck(amount.longValue(), bizType, req, riskRule);
		String riskRuleMsg = ruleCheck.check();
		if (StrKit.notBlank(riskRuleMsg)) {
			renderFail(SystemEnum.Resp.Fail.getCode()+":" + riskRuleMsg);
			return;
		}


		// 保存提现(付款、转账)订单
		TradeOrder paymentOrder = new TradeOrder();
		paymentOrder.setId(ZOIDGenerate.getUUID());
		paymentOrder.setMerchName(merch.getName());
		paymentOrder.setMerchCode(merch.getCode());
		paymentOrder.setChannelCode(tradeConfig.getChannelCode());
		paymentOrder.setBizType(bizType);
		paymentOrder.setOrderNo(ZOIDGenerate.getSixOrderNo());
		paymentOrder.setOutOrderNo(paymentOrder.getOrderNo());
		paymentOrder.setAmount(-amount.longValue());
		paymentOrder.setFee(fee.longValue());
		paymentOrder.setGoodsName(remark);

		AccountBalanceChangeResp resp = accountService.subMoney(merch.getCode(), (amount.longValue() + fee.longValue()));
		if(!"SUCCESS".equals(resp.getRespCode())){
			renderFail("钱包余额不足!");
			return;
		}
		paymentOrder.setBalance(Long.parseLong(resp.getBalance()));

		paymentOrder.setAccountName(contacts.getAccountName());
		paymentOrder.setAccountNo(contacts.getAccountNo());
		paymentOrder.setBankEnglishLetters(contacts.getBankEnglishLetters());
		paymentOrder.setBankName(contacts.getBankName());
		paymentOrder.setOpeningBankName(contacts.getOpeningBankName());
		paymentOrder.setOpeningBankNo(contacts.getOpeningBankNo());
		paymentOrder.setProvince(contacts.getProvince());
		paymentOrder.setCity(contacts.getCity());
		paymentOrder.setPhoneNo(contacts.getPhoneNo());
		paymentOrder.setCertNo(contacts.getCertsNo());
		paymentOrder.setOrderStatus(OrderStatus.FirstReview.getValue());
		paymentOrder.setRespCode(Resp.Success.getCode());
		paymentOrder.setRespMsg("已提交");
		paymentOrder.setCreateTime(ZODate.getDateTime());
		paymentOrder.setCreateUser(merchUser.getUserName());

		paymentOrder.setRealName(merch.getLegalPerson());//实名姓名或者公司名
		paymentOrder.setUserName(merchUser.getUserName());
		//钱包内转账---2019-08-22变更
		if(BizType.TransferOut.getValue().equals(paymentOrder.getBizType())){
			long payAmount = Math.abs(paymentOrder.getAmount());
			TradeOrder item = paymentOrder;
			// 收款方钱包余额加钱
			AccountBalanceChangeResp respIn = accountService.addMoney(item.getAccountNo(), payAmount);
			if (respIn.getRespCode().equals("SUCCESS")) {
				item.setAccountBalance(Long.parseLong(respIn.getBalance()));
				item.setOrderStatus(OrderStatus.Success.getValue());
				item.setRespCode(Resp.Success.getCode());
				item.setRespMsg(Resp.Success.getMsg());
				item.setPayTime(ZODate.getDateTime());
				item.setSettleDate(ZODate.getDate());
				item.setOutAccountName(item.getAccountName());
				item.setOutAccountNo(item.getAccountNo());
				//renderSuccess("转账成功");
				// 创建一笔钱包转入账的订单---手续费收取发起转账的， 转入方不收取手续费
				TradeOrder orderIn = new TradeOrder();
				orderIn.createOrderPayIn(item, BizType.TransferIn.getValue());

				MerchUser userOut = MerchUser.dao.selectByMerCode(item.getMerchCode());
				if (userOut != null) {
					// 钱包内转账收款方的 短信发送
					WalletSMS.sendSMSSubMenoy(userOut.getUserName(), payAmount, Long.parseLong(resp.getBalance()));
				}

				MerchUser user = MerchUser.dao.selectByMerCode(item.getAccountNo());
				if (user != null) {
					// 钱包内转账收款方的 短信发送
					WalletSMS.sendSMSAddMenoy(user.getUserName(), payAmount, Long.parseLong(respIn.getBalance()));
				}
			}
		}
		paymentOrder.save();
		renderSuccess(paymentOrder.getId());
	}

	/** 展示电子回单图形 */
	public void certificate() throws Exception {
		File file = new File(SystemConfig.config.get("file_center_path") + "certificate/" + getPara("id") + ".jpg");
		if (file.exists()) {
			renderFile(file);
		} else {
			TradeOrder order = TradeOrder.dao.findById(getPara("id"));
			BufferedImage image = Certificate.createImage(order);
			FileOutputStream fos = new FileOutputStream(file);
			ImageIO.write(image, "jpeg", fos);
			fos.close();
			renderFile(file);
		}
	}


	public void report() throws Exception {
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		if(merchUser == null){
			renderFail("请重新登录...");
			return;
		}
		List<Dictionary> payTypeList = Dictionary.dao.selectBizType();
		Map<String, String> payTypeMap = new HashMap<>();
		for (Dictionary payType : payTypeList) {
			payTypeMap.put(payType.getCode(), payType.getName());
		}
		Map<String, String> orderStatus = new HashMap<>();
		for (OrderStatus os : OrderStatus.values()) {
			orderStatus.put(os.getValue(), os.getName());
		}

		ZOSearchCondition sc = super.getSearchCondition();

		sc.put("orderStatus", "TS");//只需要导出成功的。
		sc.put("merchCode", merchUser.getMerchCode());
		String fileName =merchUser.getMerchCode();
		String templatePath = SystemEnum.FilePath.ReportTemplate.getValue() + "admin_trade_details.xlsx";
		String targetPath = SystemEnum.FilePath.ReportTmp.getValue() + fileName + ".xlsx";
		LinkedHashMap<String, Context> sheetNameAndData = new LinkedHashMap<>();

		int loop = SystemEnum.BizType.values().length;
		String[] templateSheetName = new String[loop];
		for(int i = 0; i < loop; i++){
			int sheetIndex = i + 1;
			templateSheetName[i] = "Sheet" + sheetIndex;
		}

		//循环遍历交易类型
		for(SystemEnum.BizType type: SystemEnum.BizType.values()) {
			sc.put("bizType", type.getValue());//导出一种交易类型
			List<TradeOrder> items = TradeOrder.dao.searchReportForAdmin(sc);

			TradeOrder allOrder = new TradeOrder();//记录金额总和
			long allAmt = 0;
			long allFee = 0;
			for (TradeOrder item : items) {
				item.setOrderStatus(orderStatus.get(item.getOrderStatus()));
				allAmt += item.getAmount();
				allFee += item.getFee();
			}
			allOrder.setMerchCode("合计");
			allOrder.setMerchName("合计");
			allOrder.setAmount(allAmt);
			allOrder.setFee(allFee);
			items.add(allOrder);
			Context context = new Context();
			context.putVar("list", items);
			sheetNameAndData.put(type.getName(), context);
		}
		ZOExcel.exportLargeData(templatePath, targetPath, sheetNameAndData, templateSheetName);
//		File file = new File(targetPath);
//		renderFile(file);

		renderSuccess("/upload/report/tmp/" + fileName + ".xlsx");

	}


	public void reportSheet() throws Exception{
		MerchUser merchUser = (MerchUser) getSession().getAttribute(MerchUser.SessionKey);
		if(merchUser == null){
			renderFail("请重新登录...");
			return;
		}

		String fileName = ZODate.getDateTime().replace(":", "-");
		String templatePath = SystemEnum.FilePath.ReportTemplate.getValue() + "sheet_trade_details.xlsx";
		String targetPath = SystemEnum.FilePath.ReportTmp.getValue() + fileName + ".xlsx";
		LinkedHashMap<String, Context> sheetNameAndData = new LinkedHashMap<>();
		int loop = 1;
		String[] templateSheetName = new String[loop];
		for(int i = 0; i < loop; i++){
			int sheetIndex = i + 1;
			templateSheetName[i] = "Sheet" + sheetIndex;
		}
		ZOSearchCondition sc = super.getSearchCondition();
		sc.put("orderStatus", "TS");//只需要导出成功的。
		sc.put("merchCode", merchUser.getMerchCode());//只需导出当前商户的

		List<TradeOrder> items = TradeOrder.dao.searchReportForAdminSheet(sc);
		Context context = new Context();
		context.putVar("list", items);
		sheetNameAndData.put("成功交易明细", context);

		ZOExcel.exportLargeData(templatePath, targetPath, sheetNameAndData, templateSheetName);
		renderSuccess("/upload/report/tmp/" + fileName + ".xlsx");
	}

}
